unit USigns;

interface

uses
  Classes, SysUtils, Graphics, Controls, Types,
// self-made units
  UMapCommon, UConfig, UCommon;

type

NSignParam = (spID, spName, spInfo, sptest);

  TSignConfig = class(TConfig)
  private
  protected
    function GetItem(Index: Integer; Param: NSignParam): string;
    procedure SetItem(Index: Integer; Param: NSignParam; const Value: string);
    function GetWItem(Index, Param: Integer): string; override;
    procedure SetWItem(Index, Param: Integer; const Value: string); override;
    function GetParamCnt: Integer; override;
    function GetParamName(Param: Integer): string; override;
  public
    property Items[Index: Integer; Param: NSignParam]: string read GetItem write
    SetItem;
    function IDString(Index: Integer; Param: NSignParam): string;
    function GetRandDefText(): string;

  end;

  CSign = class(THODObject)
  private

  public
    Deleted: Boolean;
    X, Y, ID: Integer;
    constructor Create(AX, AY: Integer; AID: Integer = 0); overload;
    constructor Create(AString: string); overload;
    procedure Edit(AX, AY, AID: Integer);
    function ToString(): string;
    function ToPoint(): TPoint;
    class procedure Split(Astr: string; out AX, AY, AID: Integer);
  end;

  CSignList = class(TObjList)
  private
    function GetItem(Index: Integer): CSign;
    procedure SetItem(Index: Integer; const Value: CSign);
  public
    function Add(const Value: CSign): Integer;
    function Find(AX, AY: Integer; FindPrm: NFindParam = fpNumber): Integer;
    function FindItemByID(ID: Integer): CSign;
    property Items[Index: Integer]: CSign read GetItem write SetItem; default;
    function GetText(AX, AY: Integer): string;
  end;

const
  SignsMapSectionName = '[Signs]';
  DefaultTextSection = 'Default';
  Delim = '|';
  SignParamColWidths: array[NSignParam] of Integer = (20, 90, 500, 20);
  SignParamColCount = Ord(High(NSignParam)) + 1;
  SignParamType: array[NSignParam] of NParamType = (npInteger, npString, npString, npBoolean);

var
  SignParamNames: array[NSignParam] of string;

function SignConfig(): TSignConfig;
function SignList(): CSignList;

implementation

uses uUtils, TypInfo;

var
  TheSignList: CSignList;
  TheSignConfig: TSignConfig;

function SignConfig(): TSignConfig;
begin
  Result := TheSignConfig;
end;

function SignList(): CSignList;
begin
  Result := TheSignList;
end;

{ TSignConfig }

function TSignConfig.GetItem(Index: Integer; Param: NSignParam): string;
begin
  if Param = spID then
    Result := IntToStr(Index)
  else
    Result := FWrapper.ReadString(IDString(Index, Param));
end;

function TSignConfig.GetParamCnt: Integer;
begin
  Result := SignParamColCount;
end;

function TSignConfig.GetParamName(Param: Integer): string;
begin
  Result := SignParamNames[NSignParam(Param)];
end;

function TSignConfig.GetRandDefText: string;
begin
  Result := Wrapper.ReadString(DefaultTextSection + Wrapper.Delim +
    IntToStr(Random(Wrapper.GetChildCount(DefaultTextSection))));
end;

function TSignConfig.GetWItem(Index, Param: Integer): string;
begin
  Result := Items[Index, NsignParam(Param)];
end;

function TSignConfig.IDString(Index: Integer; Param: NSignParam): string;
begin
  Result := Format('%d%s%s', [Index, FWrapper.Delim, SignParamNames[Param]]);
end;

procedure TSignConfig.SetItem(Index: Integer; Param: NSignParam;
  const Value: string);
begin
  if Param <> spID then
    FWrapper.WriteString(IDString(Index, Param), Value);
end;

procedure TSignConfig.SetWItem(Index, Param: Integer; const Value: string);
begin
  Items[Index, NsignParam(Param)] := Value;
end;

{ CSign }

constructor CSign.Create(AX, AY, AID: Integer);
begin
  inherited Create();
  X := AX;
  Y := AY;
  ID := AID;
end;

constructor CSign.Create(AString: string);
begin
  inherited Create();
  Split(AString, X, Y, ID);
end;

procedure CSign.Edit(AX, AY, AID: Integer);
begin
  X := AX;
  Y := AY;
  ID := AID;
end;

class procedure CSign.Split(Astr: string; out AX, AY, AID: Integer);
var
  sl : Tstringlist;
begin
  sl := Tstringlist.Create;
  try
    sl.Delimiter := delim;
    sl.DelimitedText := AStr;
    Ax := StrToIntDef(sl[0], 0);
    Ay := StrToIntDef(sl[1], 0);
    AID := StrToIntDef(sl[2], 0);
  finally
    sl.Free;
  end;
end;

function CSign.ToPoint: TPoint;
begin
  try  
    Result := Point(x, y);
  except end;
end;

function CSign.ToString: string;
begin
  Result := Format('%d%s%d%s%d', [X, delim, Y, delim, ID]);
end;


{ CSignList }

function CSignList.Add(const Value: CSign): Integer;
begin
  Result := inherited Add(Value);
end;

function CSignList.Find(AX, AY: Integer; FindPrm: NFindParam = fpNumber): Integer;
var
  j: Integer;
begin
  Result := -1;
  for j := 0 to Count - 1 do
    if (Items[j].X = AX) and (Items[j].Y = AY) then
    begin
      case FindPrm of
        fpNumber: Result := j;
        fpID: Result := Items[j].ID;
      end;
      Exit;
    end;
end;

function CSignList.FindItemByID(ID: Integer): CSign;
var
  j: Integer;
begin
  Result := nil;
  for j := 0 to Count - 1 do
    if (Items[j].ID = ID) then
    begin
      Result := Items[j];
      Exit;
    end;
end;

function CSignList.GetItem(Index: Integer): CSign;
begin
  Result := inherited Get(Index);
end;

function CSignList.GetText(AX, AY: Integer): string;
var
  id: Integer;
begin                                      
  id := Find(AX, AY, fpID);
  if (id = -1) or (id = 0)  then
    Result := SignConfig.GetRandDefText
  else
    Result := SignConfig.Items[id, spinfo];
end;

procedure CSignList.SetItem(Index: Integer; const Value: CSign);
begin
  inherited Put(Index, Value);
end;

var
  I: NSignParam;

initialization
  TheSignConfig := TSignConfig.Create(TIniWrapper);
  TheSignConfig.LoadFromFile(Path + 'data\Signs.ini');
  TheSignList := CSignList.Create();
  for i := Low(NSignParam) to High(NSignParam) do
    SignParamNames[i] := EnumText(TypeInfo(NSignParam), Ord(i)); 
    
finalization
  FreeAndNil(TheSignConfig);
  FreeAndNil(TheSignList);
end.
